package org.abc.fund.service.dataSourceCollection;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Optional;

@Service
@RequiredArgsConstructor
public class FundDataUpdateStrategyService {

    public BatchDataCollectionService.BatchCollectionConfig buildConfig(
            DataUpdatePlan plan,
            String username,
            String password,
            List<String> fundCodes
    ) {
        if (username == null || username.isBlank() || password == null || password.isBlank()) {
            throw new IllegalArgumentException("username/password cannot be empty for plan execution");
        }
        BatchDataCollectionService.BatchCollectionConfig config = new BatchDataCollectionService.BatchCollectionConfig();
        config.setUsername(username);
        config.setPassword(password);
        config.setFundCodes(fundCodes == null || fundCodes.isEmpty() ? null : List.copyOf(fundCodes));
        config.setConcurrent(true);
        config.setMode(plan.mode);
        config.setStrategy(plan.strategy);
        config.setDeleteOldBeforeInsert(plan.deleteOldBeforeInsert);
        config.setDataTypes(plan.dataTypes);
        config.setDateRange(buildDateRange(plan));
        return config;
    }

    private BatchDataCollectionService.DateRangeConfig buildDateRange(DataUpdatePlan plan) {
        BatchDataCollectionService.DateRangeConfig range = new BatchDataCollectionService.DateRangeConfig();
        switch (plan.rangeTemplate) {
            case RECENT_DAYS -> range.setRecentDays(plan.rangeValue);
            case MONTH_TO_DATE -> {
                LocalDate today = LocalDate.now();
                range.setStartDate(today.withDayOfMonth(1).toString());
                range.setEndDate(today.toString());
            }
            case LAST_QUARTER -> {
                LocalDate today = LocalDate.now();
                LocalDate start = today.minusMonths(3).withDayOfMonth(1);
                LocalDate end = today;
                range.setStartDate(start.toString());
                range.setEndDate(end.toString());
            }
            case CUSTOM -> {
                range.setStartDate(plan.customStart);
                range.setEndDate(plan.customEnd);
            }
        }
        return range;
    }

    public enum DataUpdatePlan {
        DAILY_MARKET(
                "daily-market",
                List.of("FUND_NET_VALUE", "FUND_MF_DAILY_PROFIT", "FUND_MTSS"),
                BatchDataCollectionService.BatchMode.AUTO_UPDATE,
                BatchDataCollectionService.CollectionStrategy.INCREMENTAL,
                RangeTemplate.RECENT_DAYS,
                7,
                true
        ),
        WEEKLY_LEVERAGE(
                "weekly-leverage",
                List.of("FUND_MTSS"),
                BatchDataCollectionService.BatchMode.AUTO_UPDATE,
                BatchDataCollectionService.CollectionStrategy.INCREMENTAL,
                RangeTemplate.RECENT_DAYS,
                14,
                true
        ),
        MONTHLY_FINANCIAL(
                "monthly-financial",
                List.of("FUND_FIN_INDICATOR"),
                BatchDataCollectionService.BatchMode.MANUAL_UPDATE,
                BatchDataCollectionService.CollectionStrategy.INCREMENTAL,
                RangeTemplate.LAST_QUARTER,
                0,
                false
        ),
        QUARTERLY_FULL_REFRESH(
                "quarterly-full-refresh",
                List.of("FUND_NET_VALUE", "FUND_FIN_INDICATOR", "FUND_MF_DAILY_PROFIT", "FUND_MTSS"),
                BatchDataCollectionService.BatchMode.MANUAL_UPDATE,
                BatchDataCollectionService.CollectionStrategy.FULL_RANGE,
                RangeTemplate.MONTH_TO_DATE,
                0,
                false
        );

        private final String code;
        private final List<String> dataTypes;
        private final BatchDataCollectionService.BatchMode mode;
        private final BatchDataCollectionService.CollectionStrategy strategy;
        private final RangeTemplate rangeTemplate;
        private final int rangeValue;
        private final Boolean deleteOldBeforeInsert;
        private String customStart;
        private String customEnd;

        DataUpdatePlan(String code,
                       List<String> dataTypes,
                       BatchDataCollectionService.BatchMode mode,
                       BatchDataCollectionService.CollectionStrategy strategy,
                       RangeTemplate rangeTemplate,
                       int rangeValue,
                       Boolean deleteOldBeforeInsert) {
            this.code = code;
            this.dataTypes = Collections.unmodifiableList(dataTypes);
            this.mode = mode;
            this.strategy = strategy;
            this.rangeTemplate = rangeTemplate;
            this.rangeValue = rangeValue;
            this.deleteOldBeforeInsert = deleteOldBeforeInsert;
        }

        public static Optional<DataUpdatePlan> fromCode(String code) {
            if (code == null || code.isBlank()) {
                return Optional.empty();
            }
            String normalized = code.trim().toLowerCase(Locale.ROOT);
            for (DataUpdatePlan plan : values()) {
                if (plan.code.equals(normalized)) {
                    return Optional.of(plan);
                }
            }
            return Optional.empty();
        }
    }

    private enum RangeTemplate {
        RECENT_DAYS,
        MONTH_TO_DATE,
        LAST_QUARTER,
        CUSTOM
    }
}











